#include "stdafx.h"
#include "TestUtils.h"
#include "Graph.h"
#include "VertexDirectory.h"
#include "FillGroupAlgorithmSinglesUnitTests.h"

#include <cstdlib>
#include <iostream>

using namespace std;


// Insert one vertex, return it as minimal
TestUtils::TestResult GetSingleVertexAsMinimal() 
{
	Graph g;
	Group group(0);
	vector<bool> n1(2);
	n1[0] = false;
	n1[1] = true;
	vector<bool> n2(2);
	n2[1] = false;
	n2[0] = true;
	Vertex v(n1), v2(n2);
	VertexDirectory::Clear();
	
	v.UpdateRank(1);
	v2.UpdateRank(2);
	VertexDirectory::AddVertex(&v);
	VertexDirectory::AddVertex(&v2);
	//Vertex v(vector<bool>(01));
	//VertexDirectory::AddVertex(&v);
	g.InsertVertex(&v);
	
	if (TestUtils::VerifyIsTrue(v.GetContainer() != NULL ,"Vertex was inserted to graph and container is null") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}

	if (TestUtils::VerifyIsTrue(g.IsVertexInGraph(&v), "Vertex is in graph but graph doesn't think so") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	Vertex *res = g.GetMinimalRankedVertex(&group);
	if (res==NULL)
	{
		Debug::PrintDebugMsg("Got NULL as vertex");
		return TestUtils::TestFailed;
	}
	
	if (TestUtils::VerifyIsTrue(res->Name() == v.Name(),"Did not get right minimaly ranked vertex") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}

	if (TestUtils::VerifyIsTrue(!g.IsVertexInGraph(&v), "Vertex is not in graph but graph doesn't think so") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
	// Now check where the vertex is
	return TestUtils::VerifyIsTrue(v.GetContainer() == NULL ,"Vertex was removed from graph and container is not null");	
}

// Get Minimal 2 vertices (only vertices in graph)
TestUtils::TestResult GetMinimalCouple()
{
	VertexDirectory::Clear();

	set<vector<bool>> *vertices = VertexDirectory::CreateAllVertices(4,2);
	VertexDirectory::FillVertexDirectory(vertices);

	// 100 == number of couples to check before choosing a pair with "minimal" degree
	Graph graph(100);
	Group group1(1);
	int n = 4;
	graph = TestUtils::CreateGraph4On2(graph);

	VertexSet* couple = graph.GetMinimalRankedVertexCouple(&group1);

	if (TestUtils::VerifyIsTrue(couple->Size() == 2, "wrong number of vertices returned") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;

	}

	
	Vertex* v1 = couple->Vertex1();
	Vertex* v2 = couple->Vertex2();
	// check the vertices aren't neighbours
	if (TestUtils::VerifyIsTrue(v1->Neighbours(v2) == false, "vertices are neighbours") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;

	}	

	// we cannot predict the name of the vertex so this is commented for now
	/*vector<bool> name = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name1,n))->Name();
	bool b1 = (v1->Name()) == VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name1,n))->Name();
	bool b2 = (v1->Name()) == VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name2,n))->Name();
	if (TestUtils::VerifyIsTrue(
		((v1->Name()) == VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name1,n))->Name()) || 
		( (v1->Name()) == VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name2,n))->Name()) , "Unexpected 1st vertex "+v1->PrintName())
		!= TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	if (TestUtils::VerifyIsTrue( ((v2->Name()) == VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name1,n))->Name()) || 
		( (v2->Name()) == VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name2,n))->Name()), "Unexpected 2nd vertex "+(v2->PrintName() ))
		!= TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}*/

	if (TestUtils::VerifyIsTrue( v1 != v2 , "Got same vertex twice") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
	
	return TestUtils::TestPassed;

}
// Insert 2 vertices, get the minimally ranked one
TestUtils::TestResult GetMinimalRankedVertexOutOf2DifferentRanks()
{
	Graph g;
	Group group(0);
	vector<bool> n1(2);
	n1[0] = false;
	n1[1] = true;
	vector<bool> n2(2);
	n2[1] = false;
	n2[0] = true;
	Vertex v1(n1), v2(n2);
	VertexDirectory::Clear();

	v1.UpdateRank(1);
	v2.UpdateRank(2);
	VertexDirectory::AddVertex(&v1);
	VertexDirectory::AddVertex(&v2);
	g.InsertVertex(&v1);
	g.InsertVertex(&v2);

	if (TestUtils::VerifyIsTrue(v1.GetContainer() != NULL ,"Vertex was inserted to graph and container is null") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}

	if (TestUtils::VerifyIsTrue(v2.GetContainer() != NULL ,"Vertex was inserted to graph and container is null") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}

	Vertex *res = g.GetMinimalRankedVertex(&group);
	if (res==NULL)
	{
		Debug::PrintDebugMsg("Got NULL as vertex");
		return TestUtils::TestFailed;
	}
	if (TestUtils::VerifyIsTrue(res->Name() == v1.Name(),"Did not get right minimaly ranked vertex") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed ;
	}

	if (TestUtils::VerifyIsTrue(v2.GetContainer() != NULL ,"Vertex is in graph and container is null") == TestUtils::TestFailed)
	{
		return TestUtils::TestFailed;
	}

	return TestUtils::TestPassed;
}

// Insert 2 vertices to graph, get them by rank
TestUtils::TestResult GetMinimalRankedVertexTwice()
{
	Graph g;
	Group group(0);
	vector<bool> n1(2);
	n1[0] = false;
	n1[1] = true;
	vector<bool> n2(2);
	n2[1] = false;
	n2[0] = true;
	Vertex v1(n1), v2(n2);
	v1.UpdateRank(1);
	v2.UpdateRank(2);

	VertexDirectory::Clear();
	VertexDirectory::AddVertex(&v1);
	VertexDirectory::AddVertex(&v2);
	g.InsertVertex(&v1);
	g.InsertVertex(&v2);

	

	Vertex *vertexRes = g.GetMinimalRankedVertex(&group);
	if (vertexRes==NULL)
	{
		Debug::PrintDebugMsg("Got NULL as vertex");
		return TestUtils::TestFailed;
	}
	TestUtils::TestResult res=  TestUtils::VerifyIsTrue(*vertexRes == v1,"Did not get right minimaly ranked vertex");
	if (res == TestUtils::TestFailed)
	{
		return res;
	}

	vertexRes = g.GetMinimalRankedVertex(&group);
	if (vertexRes==NULL)
	{
		Debug::PrintDebugMsg("Got NULL as vertex");
		return TestUtils::TestFailed;
	}
	return TestUtils::VerifyIsTrue(*vertexRes == v2,"Did not get right minimaly ranked vertex");
}

// Get NULL from empty graph
TestUtils::TestResult GetVertexFromEmptyGraph()
{
	Graph g;
	Group group(0);
	Vertex *vertexRes = g.GetMinimalRankedVertex(&group);
	return TestUtils::VerifyIsTrue(vertexRes == NULL,"Did not get NULL as minimal vertex from empty graph!");
}

// Add group to graph and verify
TestUtils::TestResult AddGroupToGraph()
{
	Graph graph;
	Group group(0);
	vector<bool> n1(2);
	n1[0] = false;
	n1[1] = true;
	vector<bool> n2(2);
	n2[1] = false;
	n2[0] = true;
	Vertex v1(n1), v2(n2);

	VertexDirectory::Clear();

	VertexDirectory::AddVertex(&v1);
	VertexDirectory::AddVertex(&v2);
	//Add to group
	group.InsertNewVertex(&v1);
	
	graph.AddGroup(group);
	// while not null - get all vertices and see group contains them
	if (TestUtils::VerifyIsTrue(v1.IsInGraph(),"Group wasn't inserted to graph correctly")!=TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}	

	return TestUtils::TestPassed;
}

TestUtils::TestResult CheckResettingTempContainer()
{
	// Scenario: creates graph over vertices with  n=4, w=2 
	// creates a group with 0011, 0110 and tries to fill it
	
	// Group = 1100
	// Graph = 0110, 0011, 1001, 0101, 1010
	
	VertexDirectory::Clear();

	set<vector<bool>> *vertices = VertexDirectory::CreateAllVertices(4,2);
	VertexDirectory::FillVertexDirectory(vertices);
	
	Graph graph;
	Group group1(1), group2(2);	
	
	bool name1[] = {1,1,0,0};
	int n = 4;
	Vertex *v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name1,n));
	graph.InsertVertex(v);

	bool name2[] = {0,1,1,0};
	v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name2,n));
	graph.InsertVertex(v);

	bool name3[] = {0,0,1,1};
	v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name3,n));
	graph.InsertVertex(v);
	
	bool name4[] = {1,0,0,1};
	v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name4,n));
	graph.InsertVertex(v);

	bool name5[] = {0,1,0,1};
	v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name5,n));
	graph.InsertVertex(v);

	bool name6[] = {1,0,1,0};
	v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name6,n));
	graph.InsertVertex(v);
	
	// Now create group
	bool v1Name[] = {1,1,0,0};	
	v= VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(v1Name,n));
	graph.RemoveVertex(v);
	group1.InsertNewVertex(v);

	//Get mininal vertex - can only add one vertex: 0011
	Vertex *v2 = graph.GetMinimalRankedVertex(&group1);
	bool v2Name[] = {0,0,1,1};
	Vertex *expectedV2 = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(v2Name,n));

	if (TestUtils::VerifyIsTrue( (*v2) == (*expectedV2), "vertex added to group is " + v2->PrintName()+ " and not "+expectedV2->PrintName()) != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	Vertex *v3 = graph.GetMinimalRankedVertex(&group1);
	if (TestUtils::VerifyIsTrue(v3 == NULL, "got a minimal vertex instead of NULL") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	if (TestUtils::VerifyIsTrue(graph.Count()>0, "Graph doesn't count temp group in count") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	// Now the graph is empty, all vertices are in temp group
	Vertex *v4 = graph.GetMinimalRankedVertex(&group2);
	if (TestUtils::VerifyIsTrue(v4 != NULL, "got NULL instead of minimal vertex, minimal group not restored") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}

	if (TestUtils::VerifyIsTrue(graph.Count()>0, "Graph doesn't count vertices correctly") != TestUtils::TestPassed)
	{
		return TestUtils::TestFailed;
	}
	
	return TestUtils::TestPassed;
}